home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / support / Tree.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  21.0 KB  |  654 lines

  1. /**********************************************************************************
  2.   * $Header: /private/postgres/src/support/RCS/Tree.c,v 1.2 1991/02/02 15:14:35 sp Exp $
  3.   * Tree.c: The Tree Widget Source File
  4.   *         From:
  5.   *                   The X Window System, 
  6.   *            Programming and Applications with Xt
  7.   *                   OSF/Motif Edition
  8.   *         by
  9.   *                Douglas Young
  10.   *              Prentice Hall, 1990
  11.   *
  12.   *                 Example described on pages: 397-419
  13.   *
  14.   *
  15.   *  Copyright 1989 by Prentice Hall
  16.   *  All Rights Reserved
  17.   *
  18.   * This code is based on the OSF/Motif widget set and the X Window System
  19.   *
  20.   * Permission to use, copy, modify, and distribute this software for 
  21.   * any purpose and without fee is hereby granted, provided that the above
  22.   * copyright notice appear in all copies and that both the copyright notice
  23.   * and this permission notice appear in supporting documentation.
  24.   *
  25.   * Prentice Hall and the author disclaim all warranties with regard to 
  26.   * this software, including all implied warranties of merchantability and fitness.
  27.   * In no event shall Prentice Hall or the author be liable for any special,
  28.   * indirect or cosequential damages or any damages whatsoever resulting from 
  29.   * loss of use, data or profits, whether in an action of contract, negligence 
  30.   * or other tortious action, arising out of or in connection with the use 
  31.   * or performance of this software.
  32.   *
  33.   * Open Software Foundation is a trademark of The Open Software Foundation, Inc.
  34.   * OSF is a trademark of Open Software Foundation, Inc.
  35.   * OSF/Motif is a trademark of Open Software Foundation, Inc.
  36.   * Motif is a trademark of Open Software Foundation, Inc.
  37.   * DEC is a registered trademark of Digital Equipment Corporation
  38.   * HP is a registered trademark of the Hewlett Packard Company
  39.   * DIGITAL is a registered trademark of Digital Equipment Corporation
  40.   * X Window System is a trademark of the Massachusetts Institute of Technology
  41.   **********************************************************************************/
  42.  
  43.  
  44. #include      <X11/Intrinsic.h>
  45. #include      <X11/IntrinsicP.h>
  46. #include      <X11/StringDefs.h>
  47. #include      <X11/CoreP.h>
  48. #include      <X11/CompositeP.h>
  49. #include      <X11/ConstrainP.h>
  50. #include      "Tree.h"
  51. #include      "TreeP.h"
  52. #define   MAX(a,b) ((a) > (b) ? (a) : (b))
  53.  
  54. static void             Initialize();
  55. static void             ConstraintInitialize();
  56. static void             ConstraintDestroy();
  57. static Boolean          ConstraintSetValues();
  58. static Boolean          SetValues();
  59. static XtGeometryResult GeometryManager();
  60. static void             ChangeManaged();
  61. static void             insert_new_node();
  62. static void             delete_node();
  63. static void             new_layout();
  64. static void             Redisplay();
  65. static TreeOffsetPtr    create_offset();
  66. static int              compute_positions();
  67. static void             shift_subtree();
  68. static void             set_positions();
  69. static void             reset();
  70. static Position         current_position();
  71. static void             set_current_position();
  72. static Position         sum_of_positions();
  73.  
  74. static XtResource resources[] = {
  75.  {XtNhorizontalSpace,XtCSpace,XtRDimension,sizeof(Dimension),
  76.    XtOffset(XsTreeWidget, tree.h_min_space), XtRString,"15" },
  77.  {XtNverticalSpace,XtCSpace, XtRDimension,sizeof (Dimension),
  78.    XtOffset(XsTreeWidget, tree.v_min_space), XtRString,"5"  },
  79.  {XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel),
  80.   XtOffset(XsTreeWidget, tree.foreground), XtRString,"Black"},
  81. };
  82.  
  83. static XtResource treeConstraintResources[] = {
  84.  {XtNsuperNode, XtCSuperNode, XtRPointer, sizeof(Widget),
  85.    XtOffset(TreeConstraints, tree.super_node),
  86.    XtRPointer, NULL},
  87. };
  88.  
  89. XsTreeClassRec XstreeClassRec = {
  90.   {
  91.     /* core_class fields  */
  92.     (WidgetClass) &constraintClassRec,/* superclass         */
  93.     "Tree",                           /* class_name         */
  94.     sizeof(XsTreeRec),                /* widget_size        */
  95.     NULL,                             /* class_init         */
  96.     NULL,                             /* class_part_init    */
  97.     FALSE,                            /* class_inited       */    
  98.     Initialize,                       /* initialize         */
  99.     NULL,                             /* initialize_hook    */    
  100.     XtInheritRealize,                 /* realize            */
  101.     NULL,                             /* actions            */
  102.     0,                                /* num_actions        */    
  103.     resources,                        /* resources          */
  104.     XtNumber(resources),              /* num_resources      */
  105.     NULLQUARK,                        /* xrm_class          */
  106.     TRUE,                             /* compress_motion    */    
  107.     TRUE,                             /* compress_exposure  */    
  108.     TRUE,                             /* compress_enterleave*/    
  109.     TRUE,                             /* visible_interest   */
  110.     NULL,                             /* destroy            */
  111.     NULL,                             /* resize             */
  112.     Redisplay,                        /* expose             */
  113.     SetValues,                        /* set_values         */
  114.     NULL,                             /* set_values_hook    */    
  115.     XtInheritSetValuesAlmost,         /* set_values_almost  */
  116.     NULL,                             /* get_values_hook    */    
  117.     NULL,                             /* accept_focus       */
  118.     XtVersion,                        /* version            */    
  119.     NULL,                             /* callback_private   */
  120.     NULL,                             /* tm_table           */
  121.     NULL,                             /* query_geometry     */    
  122.     NULL,                             /* display_accelerator*/
  123.     NULL,                             /* extension          */
  124.   },
  125.   {
  126.     /* composite_class fields */
  127.     GeometryManager,                 /* geometry_manager    */
  128.     ChangeManaged,                   /* change_managed      */
  129.     XtInheritInsertChild,            /* insert_child        */    
  130.     XtInheritDeleteChild,            /* delete_child        */    
  131.     NULL,                            /* extension           */
  132.   },
  133.   { 
  134.     /* constraint_class fields */
  135.    treeConstraintResources,          /* subresources        */
  136.    XtNumber(treeConstraintResources),/* subresource_count   */
  137.    sizeof(TreeConstraintsRec),       /* constraint_size     */
  138.    ConstraintInitialize,             /* initialize          */
  139.    ConstraintDestroy,                /* destroy             */
  140.    ConstraintSetValues,              /* set_values          */
  141.    NULL,                             /* extension           */
  142.    },
  143.   {
  144.     /* Tree class fields */
  145.     0,                               /* ignore              */    
  146.   }
  147. };
  148.  
  149. WidgetClass XstreeWidgetClass = (WidgetClass) &XstreeClassRec;
  150.  
  151. static void Initialize(request, new)
  152.     XsTreeWidget request, new;
  153. {
  154.   Arg       wargs[2];
  155.   XGCValues values;
  156.   XtGCMask  valueMask;
  157.   /*
  158.    * Make sure the widget's width and height are 
  159.    * greater than zero.
  160.    */
  161.   if (request->core.width <= 0)
  162.     new->core.width = 5;
  163.   if (request->core.height <= 0)
  164.     new->core.height = 5;
  165.   /*
  166.    * Create a graphics context for the connecting lines.
  167.    */
  168.   valueMask = GCForeground | GCBackground;
  169.   values.foreground = new->tree.foreground;
  170.   values.background = new->core.background_pixel;
  171.   new->tree.gc = XtGetGC (new, valueMask, &values);  
  172.   /*
  173.    * Create the hidden root widget.
  174.    */
  175.   new->tree.tree_root = (Widget) NULL;
  176.   XtSetArg(wargs[0], XtNwidth, 1);
  177.   XtSetArg(wargs[1], XtNheight, 1);
  178.   new->tree.tree_root = 
  179.           XtCreateWidget("root", widgetClass, new, wargs, 2);
  180.   /*
  181.    * Allocate the tables used by the layout
  182.    * algorithm.
  183.    */
  184.   new->tree.horizontal = create_offset(10);
  185.   new->tree.vertical   = create_offset(10);
  186.  
  187. static void ConstraintInitialize(request, new)
  188.      Widget request, new;
  189. {
  190.   TreeConstraints tree_const = TREE_CONSTRAINT(new);
  191.   XsTreeWidget tw = (XsTreeWidget) new->core.parent;
  192.   /*
  193.    * Initialize the widget to have no sub-nodes.
  194.    */
  195.   tree_const->tree.n_sub_nodes = 0;
  196.   tree_const->tree.max_sub_nodes = 0;
  197.   tree_const->tree.sub_nodes = (WidgetList) NULL;
  198.   tree_const->tree.x = tree_const->tree.y = 0; 
  199.   /*
  200.    * If this widget has a super-node, add it to that 
  201.    * widget' sub-nodes list. Otherwise make it a sub-node of 
  202.    * the tree_root widget.
  203.    */
  204.   if(tree_const->tree.super_node)
  205.     insert_new_node(tree_const->tree.super_node, new);
  206.   else
  207.     if(tw->tree.tree_root)
  208.       insert_new_node(tw->tree.tree_root, new);
  209.  
  210. static Boolean SetValues(current, request, new)
  211.     XsTreeWidget current, request, new;
  212. {
  213.  int       redraw = FALSE;
  214.  XGCValues values;
  215.  XtGCMask  valueMask;
  216.  /*
  217.   * If the foreground color has changed, redo the GC's
  218.   * and indicate a redraw.
  219.   */
  220.  if (new->tree.foreground != current->tree.foreground ||
  221.      new->core.background_pixel !=
  222.                            current->core.background_pixel){
  223.    valueMask         = GCForeground | GCBackground;
  224.    values.foreground = new->tree.foreground;
  225.    values.background = new->core.background_pixel;
  226.    XtReleaseGC(new, new->tree.gc);
  227.    new->tree.gc    = XtGetGC (new, valueMask, &values);   
  228.    redraw = TRUE;     
  229.  }
  230.  /*
  231.   * If the minimum spacing has changed, recalculate the
  232.   * tree layout. new_layout() does a redraw, so we don't
  233.   * need SetValues to do another one.
  234.   */
  235.  if (new->tree.v_min_space != current->tree.v_min_space ||
  236.      new->tree.h_min_space != current->tree.h_min_space){ 
  237.    new_layout(new);
  238.    redraw = FALSE;
  239.  }
  240.  return (redraw);
  241. }
  242.  
  243. static Boolean ConstraintSetValues(current, request, new)
  244.     Widget current, request, new;
  245. {
  246.  TreeConstraints newconst = TREE_CONSTRAINT(new);
  247.  TreeConstraints current_const = TREE_CONSTRAINT(current);
  248.  XsTreeWidget tw = (XsTreeWidget) new->core.parent;
  249.  /*
  250.   * If the super_node field has changed, remove the widget
  251.   * from the old widget's sub_nodes list and add it to the
  252.   * new one.
  253.   */
  254.  if(current_const->tree.super_node !=
  255.                                   newconst->tree.super_node){
  256.    if(current_const->tree.super_node)
  257.      delete_node(current_const->tree.super_node, new);
  258.    if(newconst->tree.super_node)
  259.      insert_new_node(newconst->tree.super_node, new);
  260.    /*
  261.     * If the Tree widget has been realized, 
  262.     * compute new layout.
  263.     */
  264.    if(XtIsRealized(tw))
  265.      new_layout(tw);
  266.   }               
  267.   return (False);
  268. }
  269.  
  270. static void insert_new_node(super_node, node)
  271.      Widget super_node, node;
  272. {
  273.   TreeConstraints super_const = TREE_CONSTRAINT(super_node);
  274.   TreeConstraints node_const = TREE_CONSTRAINT(node);
  275.   int index = super_const->tree.n_sub_nodes;
  276.   
  277.   node_const->tree.super_node = super_node;
  278.   /*
  279.    * If there is no more room in the sub_nodes array, 
  280.    * allocate additional space.
  281.    */  
  282.   if(super_const->tree.n_sub_nodes ==
  283.                              super_const->tree.max_sub_nodes){
  284.     super_const->tree.max_sub_nodes += 
  285.                     (super_const->tree.max_sub_nodes / 2) + 2;
  286.     super_const->tree.sub_nodes = 
  287.      (WidgetList) XtRealloc(super_const->tree.sub_nodes, 
  288.                            (super_const->tree.max_sub_nodes) *
  289.                             sizeof(Widget));
  290.   } 
  291.   /*
  292.    * Add the sub_node in the next available slot and 
  293.    * increment the counter.
  294.    */
  295.   super_const->tree.sub_nodes[index] = node;
  296.   super_const->tree.n_sub_nodes++;
  297. }
  298.  
  299. static void delete_node(super_node, node)
  300.     Widget  super_node, node;
  301. {
  302.   TreeConstraints node_const = TREE_CONSTRAINT(node);
  303.   TreeConstraints super_const;
  304.   int             pos, i;
  305.   /*
  306.    * Make sure the super_node exists.
  307.    */
  308.   if(!super_node) return;  
  309.   
  310.   super_const = TREE_CONSTRAINT(super_node);
  311.   /*
  312.    * Find the sub_node on its super_node's list.
  313.    */
  314.   for (pos = 0; pos < super_const->tree.n_sub_nodes; pos++)
  315.     if (super_const->tree.sub_nodes[pos] == node)
  316.       break;
  317.   if (pos == super_const->tree.n_sub_nodes) return;
  318.   /*
  319.    * Decrement the number of sub_nodes
  320.    */  
  321.   super_const->tree.n_sub_nodes--;
  322.   /*
  323.    * Fill in the gap left by the sub_node.
  324.    * Zero the last slot for good luck.
  325.    */
  326.   for (i = pos; i < super_const->tree.n_sub_nodes; i++) 
  327.     super_const->tree.sub_nodes[i] = 
  328.                             super_const->tree.sub_nodes[i+1];
  329.  super_const->tree.sub_nodes[super_const->tree.n_sub_nodes]=0;
  330. }
  331.  
  332. static void ConstraintDestroy(w) 
  333. #ifdef JUST_LIKE_BOOK  /* Unimportant but perhaps confusing */
  334.      XsTreeWidget w;
  335. #else
  336.      Widget w;
  337. #endif
  338.   TreeConstraints tree_const = TREE_CONSTRAINT(w);
  339.   int i;
  340.  /* 
  341.   * Remove the widget from its parent's sub-nodes list and
  342.   * make all this widget's sub-nodes sub-nodes of the parent.
  343.   */
  344.   if(tree_const->tree.super_node) { 
  345.     delete_node(tree_const->tree.super_node, w);
  346.     for(i=0;i< tree_const->tree.n_sub_nodes; i++)
  347.       insert_new_node(tree_const->tree.super_node, 
  348.                       tree_const->tree.sub_nodes[i]);
  349.   }
  350.   new_layout(w->core.parent);
  351. }
  352.  
  353. static XtGeometryResult GeometryManager(w, request, reply)
  354.     Widget               w;
  355.     XtWidgetGeometry    *request;
  356.     XtWidgetGeometry    *reply;
  357. {
  358.  
  359.  XsTreeWidget tw = (XsTreeWidget) w->core.parent;
  360.  /*
  361.   * No position changes allowed!.
  362.   */
  363.  if ((request->request_mode & CWX && request->x!=w->core.x)
  364.      ||(request->request_mode & CWY && request->y!=w->core.y))
  365.   return (XtGeometryNo);
  366.  /*
  367.   * Allow all resize requests.
  368.   */
  369.  if (request->request_mode & CWWidth)
  370.    w->core.width = request->width;
  371.  if (request->request_mode & CWHeight)
  372.    w->core.height = request->height;
  373.  if (request->request_mode & CWBorderWidth)
  374.    w->core.border_width = request->border_width;
  375.  /*
  376.   *  Compute the new layout based on the new widget sizes;
  377.   */
  378.  new_layout(tw);
  379.  return (XtGeometryYes);
  380. }
  381.  
  382. static void ChangeManaged(tw)
  383.     XsTreeWidget tw;
  384. {
  385.   new_layout(tw);
  386. }
  387.  
  388.  
  389. static void Redisplay (w, event, region)
  390.      XsTreeWidget   w;
  391.      XEvent        *event;
  392.      Region         region;
  393. {
  394.   int              i, j;
  395.   TreeConstraints tree_const;
  396.   Widget          child;
  397.   /*
  398.    * If the Tree widget is visible, visit each managed child.
  399.    */
  400.   if(w->core.visible)
  401.    for (i = 0; i < w -> composite.num_children; i++){
  402.      child = w -> composite.children[i];
  403.      tree_const = TREE_CONSTRAINT(child);
  404.      /*
  405.       * Draw a line between the right edge of each widget
  406.       * and the left edge of each of its sub_nodes. Don't
  407.       * draw lines from the fake tree_root.
  408.       */
  409.      if(child != w->tree.tree_root && 
  410.         tree_const->tree.n_sub_nodes)
  411.        for (j = 0; j < tree_const->tree.n_sub_nodes; j++)
  412.          XDrawLine(XtDisplay(w), XtWindow(w), 
  413.                    w->tree.gc,
  414.                    child->core.x + child->core.width, 
  415.                    child->core.y + child->core.height / 2,
  416.                    tree_const->tree.sub_nodes[j]->core.x,
  417.                    tree_const->tree.sub_nodes[j]->core.y + 
  418.                 tree_const->tree.sub_nodes[j]->core.height/2);
  419.     }
  420. }
  421.  
  422. static void new_layout(tw)
  423.      XsTreeWidget   tw;
  424. {
  425.   /*
  426.    *  Reset the auxiliary tables.
  427.    */
  428.   reset(tw->tree.vertical);
  429.   reset(tw->tree.horizontal);
  430.   /*
  431.    * Compute each widget's x,y position
  432.    */
  433.   compute_positions(tw, tw->tree.tree_root, 0);
  434.   /*
  435.    * Move each widget into place.
  436.    */
  437.   set_positions(tw, tw->tree.tree_root, 0, 0);
  438.   /*
  439.    * Trigger a redisplay of the lines connecting nodes.
  440.    */
  441.   if(XtIsRealized(tw))
  442.     XClearArea(XtDisplay(tw), XtWindow(tw), 0, 0, 0, 0, TRUE);
  443. }
  444.  
  445.  static int compute_positions(tw, w, level)
  446.      XsTreeWidget tw;
  447.      Widget       w;
  448.      long         level;
  449. {
  450.  Position       current_hpos, current_vpos;
  451.  int             i, depth = 0;
  452.  TreeConstraints tree_const = TREE_CONSTRAINT(w);
  453.  /*
  454.   * Get the current positions for this level.
  455.   */
  456.  current_hpos = current_position(tw->tree.horizontal, level);
  457.  current_vpos = current_position(tw->tree.vertical, level);
  458.  /*
  459.   * Set the current horizontal width to the max widths of all
  460.   * widgets at this level.
  461.   */
  462.  set_current_position(tw->tree.horizontal, level, 
  463.                       MAX(current_hpos, w->core.width));
  464.  /*
  465.   * If the node has no sub_nodes, just set the vertical 
  466.   * position to the next available space.
  467.   */
  468.  if(tree_const->tree.n_sub_nodes == 0){
  469.    tree_const->tree.y = current_vpos;
  470.  }
  471.  else {
  472.    Widget          first_kid, last_kid;
  473.    TreeConstraints const1, const2;
  474.    Position        top, bottom;
  475.   /*
  476.    * If the node has sub_nodes, recursively figure the 
  477.    * positions of each sub_node.
  478.    */
  479.    for(i = 0; i < tree_const->tree.n_sub_nodes; i++)
  480.     depth = compute_positions(tw, 
  481.                               tree_const->tree.sub_nodes[i],
  482.                               level + 1);
  483.   /*
  484.    * Now that the vertical positions of all children are 
  485.    * known, find the vertical extent of all sub_nodes.
  486.    */
  487.   first_kid= tree_const->tree.sub_nodes[0];
  488.   last_kid = 
  489.    tree_const->tree.sub_nodes[tree_const->tree.n_sub_nodes-1];
  490.   const1   = TREE_CONSTRAINT(first_kid);
  491.   const2   = TREE_CONSTRAINT(last_kid);
  492.   top      = const1->tree.y + first_kid->core.height / 2; 
  493.   bottom   = const2->tree.y + last_kid->core.height / 2;
  494.   /*
  495.    * Set the node's position to the center of its sub_nodes.
  496.    */
  497.   tree_const->tree.y = (top + bottom)/2 - (w->core.height/ 2);
  498.   /*
  499.    * If this position is less than the next available 
  500.    * position, correct it to be the next available
  501.    * position, calculate the amount by which all sub_nodes
  502.    * must be shifted, and shift the entire sub-tree.
  503.    */
  504.    if(tree_const->tree.y < current_vpos){
  505.      Dimension offset = current_vpos - tree_const->tree.y;
  506.      for(i = 0; i < tree_const->tree.n_sub_nodes; i++)
  507.        shift_subtree(tree_const->tree.sub_nodes[i], offset);
  508.     /*
  509.      * Adjust the next available space at all levels below
  510.      * the current level.
  511.      */
  512.      for(i = level + 1; i <= depth; i++){
  513.        Position pos = current_position(tw->tree.vertical, i);
  514.        set_current_position(tw->tree.vertical, i, pos+offset);
  515.      }
  516.      tree_const->tree.y = current_vpos;
  517.      }
  518.    }
  519.  /*
  520.   * Record the current vertical position at this level.
  521.   */
  522.   set_current_position(tw->tree.vertical, level,
  523.                        tw->tree.v_min_space + 
  524.                        tree_const->tree.y + w->core.height);
  525.   return (MAX(depth, level));
  526. }
  527.  
  528. static void shift_subtree(w, offset)
  529.      Widget     w;
  530.      Dimension  offset;
  531. {
  532.   int             i;
  533.   TreeConstraints tree_const = TREE_CONSTRAINT(w);
  534.   /*
  535.    * Shift the node by the offset.
  536.    */
  537.   tree_const->tree.y += offset; 
  538.   /*
  539.    * Shift each sub-node into place.
  540.    */
  541.   for(i=0; i< tree_const->tree.n_sub_nodes; i++)
  542.     shift_subtree(tree_const->tree.sub_nodes[i], offset);
  543. }
  544.  
  545. static void set_positions(tw, w, level)
  546.      XsTreeWidget tw;
  547.      Widget       w;
  548.      int          level;
  549. {
  550.  int               i;
  551.  Dimension         replyWidth = 0, replyHeight = 0;
  552.  XtGeometryResult  result;
  553.   
  554.  if(w){
  555.   TreeConstraints tree_const = TREE_CONSTRAINT(w);
  556.  /*
  557.   * Add up the sum of the width's of all nodes to this 
  558.   * depth, and use it as the x position.
  559.   */
  560.   tree_const->tree.x = (level * tw->tree.h_min_space) + 
  561.                 sum_of_positions(tw->tree.horizontal, level);
  562.  /*
  563.   * Move the widget into position.
  564.   */
  565.   XtMoveWidget (w, tree_const->tree.x, tree_const->tree.y);
  566.  /*
  567.   * If the widget position plus its width or height doesn't
  568.   * fit in the tree, ask if the tree can be resized.
  569.   */
  570.   if(tw->core.width < tree_const->tree.x + w->core.width ||
  571.      tw->core.height < tree_const->tree.y + w->core.height){
  572.     result = 
  573.       XtMakeResizeRequest(tw, MAX(tw->core.width, 
  574.                                   tree_const->tree.x + 
  575.                                   w->core.width),
  576.                               MAX(tw->core.height, 
  577.                                   tree_const->tree.y + 
  578.                                   w->core.height),
  579.                           &replyWidth, &replyHeight);
  580.     /*
  581.      * Accept any compromise.
  582.      */
  583.      if (result == XtGeometryAlmost)
  584.        XtMakeResizeRequest (tw, replyWidth, replyHeight, 
  585.                              NULL, NULL);
  586.   }
  587.  /*
  588.   * Set the positions of all sub_nodes.
  589.   */
  590.   for(i=0; i< tree_const->tree.n_sub_nodes;i++)
  591.     set_positions(tw, tree_const->tree.sub_nodes[i], level+1);
  592.   }
  593. }
  594.  
  595. static TreeOffsetPtr create_offset(size)
  596.    long size;
  597. {
  598.  TreeOffsetPtr  offset = 
  599.                  (TreeOffsetPtr) XtMalloc(sizeof(TreeOffset));
  600.  offset->size = size;
  601.  offset->array = 
  602.              (Dimension *) XtMalloc(size * sizeof(Dimension));
  603.  return (offset);
  604. }
  605.  
  606. static void reset(offset)
  607.    TreeOffsetPtr offset;
  608. {
  609.   long i;
  610.   for(i=0; i< offset->size; i++)
  611.     offset->array[i] = 0;
  612. }
  613.  
  614. static Position current_position(offset, position)
  615.    TreeOffsetPtr  offset;
  616.    long          position;
  617. {
  618.   if(position >= offset->size)
  619.     return (0);
  620.   return (offset->array[position]);
  621.  }
  622.  
  623. static void set_current_position(offset, index, value)
  624.    TreeOffsetPtr offset;
  625.    int           index;
  626.    Dimension     value;
  627. {
  628.  if(index >= offset->size){
  629.    offset->size = index + index / 2;
  630.    offset->array =
  631.     (Dimension *) XtRealloc(offset->array, 
  632.                             offset->size * sizeof(Dimension));
  633.  }
  634.  offset->array[index] = value;
  635. }
  636.  
  637. static Position sum_of_positions(offset, index)
  638.    TreeOffsetPtr  offset;
  639.    long           index;
  640. {
  641.   int    i;
  642.   Position  sum  = 0;
  643.   long      stop = index;
  644.   if(index > offset->size) 
  645.     stop = offset->size;
  646.   for (i=0;i < stop; i++)
  647.     sum += offset->array[i];
  648.   return (sum);
  649. }
  650.  
  651.